
package com.cn.ccp.listener;

import java.io.File;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Date;
import java.util.Scanner;

import org.apache.log4j.Logger;

public class SerialCodeUtils {
	private static Logger log = Logger.getLogger(SerialCodeUtils.class);
	public static void main(String[] args){
		System.out.println(getMachineCode());
	}
	
	
    // 生成机器码
    public static String getMachineCode() {
        BaseEncoderUtils coderUtils = new BaseEncoderUtils();
        // 获得需加密字符串
        String machineString = getDiskSerial();//getWindirDate();
        // base64编码
        String machineBase64 = coderUtils.getBASE64(machineString);
        // 混淆base64目标字符串
        String machineConfuse = confuse(machineBase64);
        return machineConfuse;
    }

    // 生成序列号
    public static String generateSerialCode(String machineCode, Date usefulLife) {
        String serialCode = null;

        BaseEncoderUtils coderUtils = new BaseEncoderUtils();
        // 还原机器码为加密字符串
        String dest = unConfuse(machineCode);
        dest = coderUtils.getFromBASE64(dest);
        // 由 有效期 和 加密字符串 构成新的字符串
        dest = dest + TimeUtils.getShortTime(usefulLife);
        // 将新的字符串进行md5编码，所得字符串即为序列号
        serialCode = coderUtils.EncoderString("MD5", dest) + "$" + TimeUtils.getShortTime(usefulLife);

        return serialCode;
    }

    // 校验序列号
    public static boolean validateSerialCode(String serialCode) {
        if (serialCode == null || serialCode.trim().length() == 0) {
            return false;
        }
        BaseEncoderUtils coderUtils = new BaseEncoderUtils();

        String[] sArray = serialCode.split("[$]");
        if (sArray.length < 2) return false;
        // 获得需加密字符串
        String machineString = getMachineCode();
        log.info("machineString = "+machineString);
        String srcMd5 = coderUtils.EncoderString("MD5", machineString + sArray[1]);
        log.info(" --srcMd5 = "+srcMd5);
        if (srcMd5.equals(sArray[0])) {
            return true;
        }

        return false;
    }

    
    // 正式版序列号校验
    public static boolean validateSerialCode2(String serialCode) {
        String[] sArray = serialCode.split("[$]");
        if (sArray.length < 3) return false;
        if (sArray[2].equals("release")) {
            return true;
        }

        return false;
    }


    // 得到过期时间
    public static Date getUsefulLife(String serialCode) {
        if (serialCode == null) return null;
        String[] sArray = serialCode.split("[$]");
        if (sArray.length < 2) return null;
        Date date = TimeUtils.getDate(sArray[1]);
        return date;
    }

    public static String getWindirDate() {
        String dirName = System.getenv("windir");
        if (dirName == null) {
            throw new IllegalArgumentException("Register fail. Error code is 01.");
        } else {
            dirName += File.separatorChar + "system32" + File.separatorChar + "config";
        }
        log.info("--------------dirName = "+dirName);
        File folder = new File(dirName);
        if (folder.exists()) {
            Date dirDate = new Date();
            dirDate.setTime(folder.lastModified());
            return TimeUtils.getLongTime(dirDate);
        } else {
            throw new IllegalArgumentException("Register fail. Error code is 02.");
        }
    }

    // 混淆字符串
    private static String confuse(String src) {
        char[] srcChars = src.toCharArray();
        StringBuffer dest = new StringBuffer();
        int length = srcChars.length;
        int loop = 0;
        if (length % 2 == 0) {
            loop = length / 2;
        } else {
            loop = (length - 1) / 2;
        }

        for (int i = 0; i < loop; i++) {
            dest.append(srcChars[i]).append(srcChars[i + loop]);
        }
        if (length % 2 != 0) {
            dest.append(srcChars[srcChars.length - 1]);
        }

        return dest.toString();
    }
    
    
    private static String getDiskSerial(){
    	 try{
			 Process process = Runtime.getRuntime().exec(
			 new String[] { "wmic", "cpu", "get", "ProcessorId" });
			 process.getOutputStream().close();
			 Scanner sc = new Scanner(process.getInputStream());
			 String property = sc.next();
			 String serial = sc.next();
//			 System.out.println(property + ": " + serial);
			 return serial;
		 }catch(Exception e){
			 log.error("get disk serial failed :", e);
			 return getMACAddress();
		 }
    }
    
  //获取MAC地址的方法
    private static String getMACAddress(){
    	StringBuffer sb = new StringBuffer();
    	try{
	        //获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。
	        byte[] mac = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getHardwareAddress();
	        //下面代码是把mac地址拼装成String
	        for(int i=0;i<mac.length;i++){
	            if(i!=0){
	                sb.append("-");
	            }
	            //mac[i] & 0xFF 是为了把byte转化为正整数
	            String s = Integer.toHexString(mac[i] & 0xFF);
	            sb.append(s.length()==1?0+s:s);
	        }
    	}catch(Exception e){
    		log.error("get mac address failed :", e);
    		sb.append("1234567890");
    	}
        //把字符串所有小写字母改为大写成为正规的mac地址并返回
        return sb.toString().toUpperCase();
    }
	
    
    
    
    
    
    // 还原被混淆的字符串
    private static String unConfuse(String src) {
        char[] srcChars = src.toCharArray();
        StringBuffer dest = new StringBuffer();
        int length = srcChars.length;
        int loop = 0;
        if (length % 2 == 0) {
            loop = length / 2;
        } else {
            loop = (length - 1) / 2;
        }

        StringBuffer buf1 = new StringBuffer();
        StringBuffer buf2 = new StringBuffer();
        for (int i = 0; i < loop; i++) {
            buf1.append(srcChars[i * 2]);
            buf2.append(srcChars[i * 2 + 1]);
        }
        dest.append(buf1).append(buf2);
        if (length % 2 != 0) {
            dest.append(srcChars[srcChars.length - 1]);
        }

        return dest.toString();
    }
}
